# -*- coding: utf-8 -*-

# addVar(lb=0.0, ub=float('inf'), obj=0.0, vtype=GRB.CONTINUOUS, name='', column=None)
    
import gurobipy as gp
from gurobipy import *


# # 创建一个新的模型
# m = gp.Model("example")

# # 添加约束
# c1 = m.addConstr(0, GRB.LESS_EQUAL, 10, name="c1")
# c2 = m.addConstr(0, GRB.LESS_EQUAL, 15, name="c2")

# # 使用column参数添加变量
# x = m.addVar(lb=0, ub=GRB.INFINITY, obj=3, vtype=GRB.CONTINUOUS, name="x", column=gp.Column([1, 2], [c1, c2]))
# y = m.addVar(lb=0, ub=GRB.INFINITY, obj=2, vtype=GRB.CONTINUOUS, name="y", column=gp.Column([1, 1], [c1, c2]))

# # 打印模型
# m.printStats()

# # 优化模型
# m.optimize()

# # 打印结果
# if m.status == GRB.OPTIMAL:
#     print('Optimal solution found:')
#     print(f'x = {x.x}')
#     print(f'y = {y.x}')
#     print(f'Objective value = {m.objVal}')
# else:
#     print('No optimal solution found')

# m = gp.Model("example")
# m.setParam('OutputFlag', 0)
# x = m.addVar(lb= -10, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, obj=3, name='x')
# y = m.addVar(lb=-100, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, obj=2, name='y')
# print(x)

# m.addConstr(x * y <= 10, name="c1")
# # m.addConstr((x ** 2)- (pow(y, 0.5)) <= 15, name="c2")
# z = m.addVar(vtype=GRB.CONTINUOUS, name='z')  # 用于存储 y 的 0.5 次方
# m.addGenConstrPow(y, z, 3.5, name="pow_constr")  # y 的 0.5 次方存储在 z 中
# m.addConstr(x * x - z <= 15, name="c2")

# m.optimize()

# if m.Status == GRB.OPTIMAL:
#     print(f'Optimal solution is {x.x}, {y.x}')
#     print(f'Optimal value is {m.objVal}')
# else:
#     print("No solution!")



# m = gp.Model()
# x = m.addVars([(3,'a'), (3,'b'), (7,'b'), (7,'c')])
# x = m.addVars([3, 7],['a', 'b'], ['c', 'd'], name='x')
# x = m.addVars([1, 2, 3, 4], name='x')
# x = m.addVars(1, 2, 3, 4, name='x')
# x = m.addVars({
#     (1, 2) : 1
#     })
# print(x)


# m = gp.Model()
# z = m.addVars(3, obj=[1.0, 2.0, 1.2])
# x = m.addVar(vtype=GRB.CONTINUOUS, name="x")
# y = m.addVar(vtype=GRB.CONTINUOUS, name="y")
# print(type(x))
# print(type(z))

# m.setObjective(x + y, GRB.MINIMIZE)
# print(m.getObjective())


# x = m.addVar(vtype=GRB.CONTINUOUS, name="x")
# y = m.addVar(vtype=GRB.CONTINUOUS, name="y")

# # 设置目标函数
# m.setObjective(x + 2 * y, GRB.MAXIMIZE)

# # 添加约束条件
# m.addConstr(x + y <= 10, "c1")
# m.addConstr(2 * x + y <= 15, "c2")
# m.addConstr(x >= 0, "c3")
# m.addConstr(y >= 0, "c4")
# # 获取目标函数对象
# obj = m.getObjective()

# # 构建目标函数的字符串表示
# obj_str = " + ".join(f"{coeff} * {var.varName}" for var, coeff in obj.getLinExpr().getVarsAndCoeffs())
# print('Objective function:', obj_str)





# m = gp.Model()
# m.setParam('OutputFlag', 0) # 优化完成后不打印许可和/或计算服务器信息

# # 添加变量
# x = m.addVar(ub=1000, vtype=GRB.CONTINUOUS, name="x")
# y = m.addVar(ub=500, vtype=GRB.CONTINUOUS, name="y1")
# z = m.addVars(3, name=["z1", "z2", "z3"])

# ztcoef = { 0 : 11, 1 : 12, 2 : 8 }

# # 设置目标函数
# m.setObjective(-300 * x + 2 * y + z.prod(ztcoef), GRB.MAXIMIZE)

# # 添加约束条件
# zccoef = { 0 : 1, 1 : 2, 2 : 8 }
# m.addConstr(x + y >= 1000, "c1")
# m.addConstr(2 * x - y + z.prod(zccoef) <= 2500, "c2")
# m.addConstr(0 <= x, "c3")
# m.addConstr(y >= 0, "c4")

# # 必须要更新模型，才能在python中获得这些模型的表达式
# m.update()

# # 打印目标函数
# obj = m.getObjective() 
# print('Objective function:', obj) 
# # 打印所有约束条件
# for constr in m.getConstrs():
#     left_hand_side_terms = []
#     # 获取约束类型并转换为相应符号
#     if constr.sense == GRB.LESS_EQUAL:
#         sense_symbol = "<="
#     elif constr.sense == GRB.GREATER_EQUAL:
#         sense_symbol = ">="
#     elif constr.sense == GRB.EQUAL:
#         sense_symbol = "=="
#     else:
#         sense_symbol = "Unknown"
#     # 遍历所有变量，找出在约束中有非零系数的变量
#     for var in m.getVars():
#         coeff = m.getCoeff(constr, var)
#         if coeff != 0:
#             if coeff == 1:
#                 left_hand_side_terms.append(var.varName)
#             elif coeff == -1:
#                 left_hand_side_terms.append(f"-{var.varName}")
#             else:
#                 left_hand_side_terms.append(f"{coeff} * {var.varName}")
#     # 构建左侧表达式字符串
#     left_hand_side = " + ".join(left_hand_side_terms)
#     # 处理可能出现的 "+ -" 情况
#     left_hand_side = left_hand_side.replace("+ -", "- ")
#     # 获取约束右侧常数
#     right_hand_side = constr.RHS
#     # 打印完整约束表达式
#     print(f'Constraint: {constr.constrName} : {left_hand_side} {sense_symbol} {right_hand_side}')

# m.optimize()
# if m.Status == GRB.OPTIMAL:
#     print(f'Optimal solution is x = {x.x}, y1 = {y.x}, z = {[z[i].x for i in range(3)]}')
#     print(f'Optimal value is {m.objVal}')
# else:
#     print("No solution!")

# m.write("test2.lp")





# m = gp.Model()

# # 添加变量，指定目标函数系数
# z = m.addVars(3, obj=[1.0, 2.0, 1.2])

# # 设置目标函数为最小化 z[0] + z[1] + z[2]
# m.setObjective(z.sum(), GRB.MINIMIZE)

# # 打印目标函数
# obj = m.getObjective()
# print(obj)


# 打印变量
# for i, var in z.items():
#     print(f'Variable {i}: {var}')











# # 订单
# ORDERS = ['O1', 'O2']

# # 工序
# STEPS = [1]

# # 设备
# RESOURCES = ['R1']

# # 模具
# MOULDS = ['M1']

# # 各种统计数据
# nORDERS = len(ORDERS)
# nSTEPS = len(STEPS)
# nRESOURCES = len(RESOURCES)
# nMOULDS = len(MOULDS)
# # 时段数量
# SLOTS = range(nORDERS * nSTEPS)

# ###############################   模型   ###################################

# # 创建模型
# model = gp.Model('AssemblyAPS')

# # 变量： 每个订单每道工序的起始时间和终止时间
# start = model.addVars(ORDERS, STEPS, vtype=GRB.INTEGER, name="start")
# end = model.addVars(ORDERS, STEPS, vtype=GRB.INTEGER, name="end")

# # 变量：每个设备/模具 每个时段上对应的每个订单每道工序起始时间和终止时间
# startR = model.addVars(RESOURCES, SLOTS, ORDERS, STEPS,
#                        vtype=GRB.INTEGER, name="startR")

# startM = model.addVars(MOULDS, SLOTS, ORDERS, STEPS,
#                        vtype=GRB.INTEGER, name="startM")
# endR = model.addVars(RESOURCES, SLOTS, ORDERS, STEPS,
#                      vtype=GRB.INTEGER, name="endR")
# endM = model.addVars(MOULDS, SLOTS, ORDERS, STEPS,
#                      vtype=GRB.INTEGER, name="endM")

# print(startR)
# print(startM)
# print(endR)
# print(endM)



# m = gp.Model()

# x = m.addVar(ub=1000, vtype=GRB.CONTINUOUS, name="x")
# y = m.addVar(ub=500, vtype=GRB.CONTINUOUS, name="y")
# z = m.addVar(ub=500, vtype=GRB.CONTINUOUS, name="z")


# e = x + 2 * y + 3

# e.add(x + y, (2, 1))
# m.update()
# print(e)


# e1 = LinExpr(2.0)
# e2 = LinExpr(x)
# e3 = LinExpr(2 * x)
# e4 = LinExpr([1.0, 2.0], [x, y])
# e5 = LinExpr([(1.0, x), (2.0, y), (1.0, z)])
# m.update()
# for i, expr in enumerate([e1, e2, e3, e4, e5], 1) :
#     print(f'e{i} : {expr}')



# m = gp.Model("IAddExample")

# x = m.addVar(name="x")
# y = m.addVar(name="y")

# expr = gp.LinExpr([1, 1], [x, y])  # 表达式 x + y
# # expr1 = expr + y
# # expr1 += x  # 相当于调用 expr.__iadd__(x)

# # m.update()
# # print(expr1)

# expr.addTerms(1.0, x)
# expr.addTerms([2.0, 3.0], [x, y])

# m.update()
# print(expr)


# m = gp.Model("IAddExample")

# x = m.addVar(name="x")
# y = m.addVar(name="y")

# expr = gp.quicksum([1 * x, 2 * y])

# m.update()
# print(expr)





# m = gp.Model()
# m.setParam('OutputFlag', 0) # 优化完成后不打印许可和/或计算服务器信息

# # 添加变量
# x = m.addVar(ub=1000, vtype=GRB.CONTINUOUS, name="x")
# y = m.addVar(ub=500, vtype=GRB.CONTINUOUS, name="y1")
# z = m.addVars(3, name=["z1", "z2", "z3"])

# ztcoef = { 0 : 11, 1 : 12, 2 : 8 }

# # 设置目标函数
# m.setObjective(-300 * x + 2 * y + z.prod(ztcoef), GRB.MAXIMIZE)
# print(type(z.prod(ztcoef)))

# # 添加约束条件
# zccoef = { 0 : 1, 1 : 2, 2 : 8 }
# m.addConstr(x + y >= 1000, "c1")
# m.addConstr(2 * x - y + z.prod(zccoef) <= 2500, "c2")
# m.addConstr(0 <= x, "c3")
# m.addConstr(y >= 0, "c4")

# m.update()
# var =m.getVars()
# constrs = m.getConstrs()

# print(var)
# # for constr in m.getConstrs():
# #     expr = constr.getExpr()

# import numpy as np
# m = gp.Model("IAddExample")

# x = m.addVar(name="x")
# y = m.addVar(name="y")
# m.update()


# expr = gp.quicksum([np.dot(np.array(m.getVars()), np.array([1, 2]))])

# print(expr)


# m = gp.Model()
# x = m.addVars(5, 5, name="x")
# capacity = [1, 2, 3, 4, 5]
# const = m.addConstrs(x.sum(i, '*') <= capacity[i] for i in range(5))
# m.update()
# print(const)


# m = gp.Model()
# x = m.addVars(5, name="x")
# m.addConstrs(x[i] + x[j] <= 1 for i in range(5) for j in range(5))
# m.update()
# expr = (x[i] + x[j] <= 1 for i in range(5) for j in range(5))
# print(type(expr))


m = gp.Model()
x = m.addVars(5, name="x")
y = m.addVars(5, name="y")
ww = m.addConstrs((x[i]*x[i] + y[i]*y[i] + 2 * y[i] <= 2 for i in range(5)), name="c")
m.update()
for consstrsub, Qconstrexpr in ww.items():
    print(type(Qconstrexpr))
    Qcname = Qconstrexpr.QCName
    curleftside = m.getQCRow(Qconstrexpr)
    sense = Qconstrexpr.QCSense
    sense_mapping = {'<': '<=', '>': '>=', '=': '='}
    cursense = sense_mapping[sense]
    currhs = Qconstrexpr.QCRHS
    print(f'{Qcname}: {curleftside} {cursense} {currhs}')

# import numpy as np
# m = gp.Model()
# x = m.addVars(5, 5, vtype=GRB.INTEGER, name="x")
# mm = m.addConstrs(x.sum(i, '*') == [-2000000000000, 200000000000000] for i in [1, 2, 4])
# m.update()

# subset, val = multidict(x)

# subinconstr = tuplelist([])
# for i in [1, 2, 4]:
#     subinconstr += (subset.select(i, '*'))


# subtovarinm = {sub: x[sub] for sub in subinconstr}
# subtovarinm = tupledict(subtovarinm)

# coef = tupledict({})
# count = 1
# for sub in subinconstr:
#     coef[sub] = count
#     # count += 1
    

# m.setObjective(subtovarinm.prod(coef), GRB.MAXIMIZE)
# m.update()
# obj = m.getObjective() 
# print('Objective function:', obj) 
# for consstrsub, Gconstrexpr in mm.items():
#     # print(type(Gconstrexpr))
#     Qcname = Gconstrexpr.ConstrName
#     curleftside = m.getRow(Gconstrexpr)
#     sense = Gconstrexpr.Sense
#     sense_mapping = {'<': '<=', '>': '>=', '=': '='}
#     cursense = sense_mapping[sense]
#     # print(type(sense))
#     currhs = Gconstrexpr.RHS
#     print(f'{Qcname}: {curleftside} {cursense} {currhs}')


# m.addConstrs(z[i] == max_(x[i], y[i]) for i in range(5))
# m.addConstrs((x[i] == 1) >> (y[i] + z[i] <= 5) for i in range(5))



# # 打印目标函数
# obj = m.getObjective() 
# print('Objective function:', obj) 
# 打印所有约束条件
# for constr in m.getConstrs():
#     sense_mapping = {GRB.LESS_EQUAL : '<=', GRB.GREATER_EQUAL: '>=', GRB.EQUAL: '='}
#     sense_symbol = sense_mapping[constr.sense]
#     left_hand_side = m.getRow(constr)
#     right_hand_side = constr.RHS
#     # 打印完整约束表达式
#     print(f'Constraint: {constr.constrName} : {left_hand_side} {sense_symbol} {right_hand_side}')

import numpy as np
m = gp.Model()
Q = np.full((2, 3), 1)   
xL = m.addMVar(2)
xR = m.addMVar(3)
kk = m.addMQConstr(Q, None, '<', 1.0, xL, xR)

m.update()
print(kk)
print(xL)
print(xR)
print(m.getVars())